#include "cachepathinfo.h"
#include "unifiedcachemanager.h"
#include "fileidentitymanager.h"
#include <QStandardPaths>
#include <QRegularExpression>

// === 构造函数 ===

CachePathInfo::CachePathInfo(const QString& actualCacheDirectory)
    : m_actualCacheDirectory(actualCacheDirectory)
    , m_createdTime(QDateTime::currentDateTime())
{
}

CachePathInfo::CachePathInfo(const QString& actualCacheDirectory, const QString& fileIdentity)
    : m_actualCacheDirectory(actualCacheDirectory)
    , m_createdTime(QDateTime::currentDateTime())
{
    Q_UNUSED(fileIdentity) // 预留参数，未来可能用于验证
}

// === Martin Fowler Strategy Pattern: 路径计算策略 ===

QString CachePathInfo::getActualCacheDirectory() const
{
    if (!m_actualCacheDirectory.isEmpty()) {
        return normalizePath(m_actualCacheDirectory);
    }

    // Fallback to global configuration
    return getCurrentGlobalCacheDirectory();
}

QString CachePathInfo::getFullCacheDirectory(const QString& fileIdentity) const
{
    QString baseCacheDir = getActualCacheDirectory();
    QString cacheKey = FileIdentityManager::getCacheKey(fileIdentity);
    return QDir(baseCacheDir).absoluteFilePath(cacheKey);
}

QString CachePathInfo::getPageCacheFilePath(const QString& fileIdentity, int pageIndex) const
{
    QString cacheDir = getFullCacheDirectory(fileIdentity);
    QString fileName = generatePageFileName(pageIndex);
    return QDir(cacheDir).absoluteFilePath(fileName);
}

QString CachePathInfo::getThumbnailCacheDirectory(const QString& fileIdentity) const
{
    QString fullCacheDir = getFullCacheDirectory(fileIdentity);
    return QDir(fullCacheDir).absoluteFilePath("thumbnails");
}

QString CachePathInfo::getThumbnailCacheFilePath(const QString& fileIdentity, int thumbnailIndex) const
{
    QString thumbnailDir = getThumbnailCacheDirectory(fileIdentity);
    QString fileName = generateThumbnailFileName(thumbnailIndex);
    return QDir(thumbnailDir).absoluteFilePath(fileName);
}

// === 缓存目录管理 ===

void CachePathInfo::setActualCacheDirectory(const QString& directory)
{
    m_actualCacheDirectory = normalizePath(directory);
    m_createdTime = QDateTime::currentDateTime();
}

bool CachePathInfo::cacheDirectoryExists(const QString& fileIdentity) const
{
    QString fullCacheDir = getFullCacheDirectory(fileIdentity);
    return QDir(fullCacheDir).exists();
}

bool CachePathInfo::ensureCacheDirectoryExists(const QString& fileIdentity) const
{
    QString fullCacheDir = getFullCacheDirectory(fileIdentity);
    bool success = QDir().mkpath(fullCacheDir);
    return success;
}

bool CachePathInfo::removeCacheDirectory(const QString& fileIdentity) const
{
    QString fullCacheDir = getFullCacheDirectory(fileIdentity);
    QDir dir(fullCacheDir);
    if (dir.exists()) {
        return dir.removeRecursively();
    }
    return true; // 目录不存在也算成功
}

// === 路径兼容性处理 ===

bool CachePathInfo::isUsingGlobalConfig() const
{
    return m_actualCacheDirectory.isEmpty();
}

void CachePathInfo::updateToGlobalConfig(const QString& newGlobalCacheDirectory)
{
    m_actualCacheDirectory = normalizePath(newGlobalCacheDirectory);
    m_createdTime = QDateTime::currentDateTime();
}


// === 实用工具方法 ===

QString CachePathInfo::generatePageFileName(int pageIndex)
{
    return QString("page_%1.png").arg(pageIndex, 5, 10, QChar('0'));
}

QString CachePathInfo::generateThumbnailFileName(int thumbnailIndex)
{
    return QString("thumb_%1.png").arg(thumbnailIndex, 5, 10, QChar('0'));
}

int CachePathInfo::parsePageIndexFromFileName(const QString& fileName)
{
    // 匹配 "page_00001.png" 格式
    QRegularExpression regex(R"(page_(\d+)\.png)");
    QRegularExpressionMatch match = regex.match(fileName);

    if (match.hasMatch()) {
        bool ok;
        int index = match.captured(1).toInt(&ok);
        return ok ? index : -1;
    }

    return -1;
}

// === 调试和状态信息 ===

QString CachePathInfo::getStatusInfo(const QString& fileIdentity) const
{
    QString info;
    info += QString("CachePathInfo Status:\n");
    info += QString("  Actual Cache Dir: %1\n").arg(m_actualCacheDirectory.isEmpty() ? "[Using Global]" : m_actualCacheDirectory);
    info += QString("  Created Time: %1\n").arg(m_createdTime.toString("yyyy-MM-dd hh:mm:ss"));
    info += QString("  Using Global Config: %1\n").arg(isUsingGlobalConfig() ? "Yes" : "No");

    if (!fileIdentity.isEmpty()) {
        info += QString("  Full Cache Dir: %1\n").arg(getFullCacheDirectory(fileIdentity));
        info += QString("  Directory Exists: %1\n").arg(cacheDirectoryExists(fileIdentity) ? "Yes" : "No");
    }

    return info;
}

bool CachePathInfo::isValid() const
{
    QString actualDir = getActualCacheDirectory();
    return !actualDir.isEmpty() && QDir(actualDir).exists();
}

// === 序列化支持 ===

QString CachePathInfo::toString() const
{
    QStringList parts;
    parts << m_actualCacheDirectory;
    parts << m_createdTime.toString(Qt::ISODate);
    return parts.join("|");
}

CachePathInfo CachePathInfo::fromString(const QString& str)
{
    QStringList parts = str.split("|");
    CachePathInfo info;

    if (parts.size() >= 1) {
        info.m_actualCacheDirectory = parts[0];
    }

    if (parts.size() >= 2) {
        info.m_createdTime = QDateTime::fromString(parts[1], Qt::ISODate);
    }

    if (!info.m_createdTime.isValid()) {
        info.m_createdTime = QDateTime::currentDateTime();
    }

    return info;
}

// === 比较操作符 ===

bool CachePathInfo::operator==(const CachePathInfo& other) const
{
    return m_actualCacheDirectory == other.m_actualCacheDirectory;
}

bool CachePathInfo::operator!=(const CachePathInfo& other) const
{
    return !(*this == other);
}

// === 私有工具方法 ===

QString CachePathInfo::getCurrentGlobalCacheDirectory() const
{
    // 通过UnifiedCacheManager获取当前全局缓存目录
    UnifiedCacheManager* cacheManager = UnifiedCacheManager::instance();
    if (cacheManager) {
        return cacheManager->getCacheDirectory();
    }

    // 最后的fallback
    return QStandardPaths::writableLocation(QStandardPaths::CacheLocation);
}

QString CachePathInfo::normalizePath(const QString& path)
{
    return QDir::cleanPath(path);
}

// === QDebug支持 ===

QDebug operator<<(QDebug debug, const CachePathInfo& pathInfo)
{
    debug.nospace() << "CachePathInfo("
                   << "path:" << pathInfo.getActualCacheDirectory() << ")";
    return debug;
}